home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / plan / src / dayedit.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  319 lines

  1. /*
  2.  * Handle all the more complicated user interactions with an entry list menu.
  3.  * Whenever the user begins editing a row, the entry in that row is copied
  4.  * to the edit struct. All editing takes place, until it is confirmed and
  5.  * put back into the main list. The reason for this is that entering a new
  6.  * date or time doesn't make the row disappear from the current list because
  7.  * it now belongs to a different day before editing is finished.
  8.  *
  9.  *    got_entry_press(lw, x, y, on)    The user pressed on one of the
  10.  *                    buttons in the list menu button array.
  11.  *    confirm_new_entry()        Puts the currently edited row back
  12.  *                    into the mainlist, and re-sorts.
  13.  *    undo_new_entry()        Kill the edit buffer, undoing the
  14.  *                    changes to the current row.
  15.  *    got_entry_text(lw, x, y, text)    The user entered text into the text
  16.  *                    button. There is never more than one.
  17.  *    sensitize_edit_buttons()    Desensitize all buttons in the
  18.  *                    bottom button row that don't make
  19.  *                    sense at the moment.
  20.  */
  21.  
  22. #ifndef MIPS
  23. #include <stdlib.h>
  24. #endif
  25. #include <time.h>
  26. #include <Xm/Xm.h>
  27. #include "cal.h"
  28.  
  29. extern time_t        parse_datestring(), parse_timestring();
  30. extern void        parse_warnstring();
  31. extern char        *mkbuttonstring(), *mkdatestring();
  32. extern char        *mystrdup();
  33. extern struct tm    *time_to_tm();
  34. extern time_t        get_time();
  35.  
  36. extern struct config    config;        /* global configuration data */
  37. extern struct list    *mainlist;    /* list of all schedule entries */
  38. extern int        curr_month;    /* month being displayed, 0..11 */
  39. extern int        curr_year;    /* year being displayed, since 1900 */
  40.  
  41. struct edit        edit;        /* info about entry being edited */
  42.  
  43.  
  44. got_entry_press(lw, x, y, on)
  45.     struct listmenu        *lw;        /* which menu */
  46.     int            x, y;        /* which column/row */
  47.     int            on;        /* enable radio but: on/off */
  48. {
  49.     register struct entry    *ep;        /* affected entry */
  50.     int            num;        /* number of entries so far */
  51.     time_t            now;        /* current time */
  52.  
  53.     num = lw->sublist ? lw->sublist->nentries : 0;
  54.     if (y-1 > num)                    /* illegal entry? */
  55.         return;
  56.     if (edit.editing && (edit.y != y || edit.menu != lw))
  57.         confirm_new_entry();
  58.     if (!edit.editing) {
  59.         if (y-1 < num)
  60.             clone_entry(&edit.entry, lw->sublist->entry[y-1]);
  61.         else {
  62.             clone_entry(&edit.entry, (struct entry *)0);
  63.             now = get_time();
  64.             edit.entry.time = lw->time ? lw->time : now - now%60;
  65.         }
  66.         edit.editing = TRUE;
  67.         edit.changed = FALSE;
  68.         edit.y       = y;
  69.         edit.menu    = lw;
  70.         sensitize_edit_buttons();
  71.     }
  72.     ep = &edit.entry;
  73.     switch(x) {
  74.       case SC_ENABLE:
  75.         ep->suspended = !on;
  76.         edit.changed = TRUE;
  77.         sensitize_edit_buttons();
  78.         update_all_listmenus();
  79.         break;
  80.  
  81.       case SC_TIME:
  82.         if (lw->time && !lw->period &&
  83.                 (!lw->sublist || y > lw->sublist->nentries))
  84.             print_button(lw->entry[y][SC_DATE],
  85.                 mkdatestring(lw->time ? lw->time : now));
  86.         edit_list_button(TRUE, lw, x, y);
  87.         break;
  88.  
  89.       case SC_LENGTH:
  90.         if (ep->notime)
  91.             break;
  92.       case SC_DATE:
  93.       case SC_NOTE:
  94.         edit_list_button(TRUE, lw, x, y);
  95.         break;
  96.  
  97.       case SC_ADVANCE:
  98.         if (ep->notime)
  99.             break;
  100.         if (config.bigwarning)
  101.             edit_list_button(TRUE, lw, x, y);
  102.         else
  103.             create_advance_popup();
  104.         break;
  105.  
  106.       case SC_RECYCLE:
  107.         create_recycle_popup();
  108.         break;
  109.  
  110.       case SC_MESSAGE:
  111.         create_text_popup("Message", &edit.entry.message, x);
  112.         break;
  113.  
  114.       case SC_SCRIPT:
  115.         if (ep->notime)
  116.             break;
  117.         create_text_popup("Shell Script", &edit.entry.script, x);
  118.         break;
  119.  
  120.       case SC_MEETING:
  121. #if 0 /*<<< not yet implemented */
  122.         create_text_popup("Meeting", &edit.entry.meeting, x);
  123. #endif
  124.         break;
  125.  
  126.       case SC_PRIVATE:
  127.         ep->private ^= TRUE;
  128.         edit.changed = TRUE;
  129.         sensitize_edit_buttons();
  130.         update_all_listmenus();
  131.         break;
  132.     }
  133. }
  134.  
  135.  
  136. /*
  137.  * confirm new entry, put it in the list
  138.  */
  139.  
  140. confirm_new_entry()
  141. {
  142.     BOOL            changed;
  143.     struct tm        new;
  144.     struct tm        old;
  145.  
  146.     edit_list_button(FALSE, edit.menu, 0, 0);
  147.     changed = edit.editing && edit.changed;
  148.     destroy_text_popup();
  149.     destroy_recycle_popup();
  150.     destroy_advance_popup();
  151.     new = *time_to_tm(edit.entry.time);
  152.     old = new;
  153.     if (changed) {
  154.         mainlist->locked++;
  155.         if (!edit.menu->sublist ||
  156.             edit.y-1 >= edit.menu->sublist->nentries)
  157.             (void)add_entry(&mainlist, &edit.entry);
  158.         else {
  159.             struct entry *ep = edit.menu->sublist->entry[edit.y-1];
  160.             old = *time_to_tm(ep->time);
  161.             delete_entry(mainlist, ep - mainlist->entry);
  162.             (void)add_entry(&mainlist, &edit.entry);
  163.         }
  164.         rebuild_repeat_chain(mainlist);
  165.         mainlist->locked--;
  166.     }
  167.     destroy_entry(&edit.entry);
  168.     edit.editing = FALSE;
  169.     edit.changed = FALSE;
  170.     sensitize_edit_buttons();
  171.     if (changed) {
  172.         update_all_listmenus();
  173.         if (old.tm_mday != new.tm_mday &&
  174.             old.tm_mon == curr_month && old.tm_year == curr_year)
  175.             draw_day_notes(old.tm_mday);
  176.         if (new.tm_mon == curr_month && new.tm_year == curr_year)
  177.             draw_day_notes(new.tm_mday);
  178.         if (old.tm_mday != new.tm_mday)
  179.             draw_year_day_notes(old.tm_mday, old.tm_mon,
  180.                             old.tm_year, FALSE);
  181.         draw_year_day_notes(new.tm_mday, new.tm_mon,
  182.                             new.tm_year, FALSE);
  183.         draw_week_day(new.tm_mday, new.tm_mon, new.tm_year);
  184.         mainlist->modified = TRUE;
  185.     }
  186. }
  187.  
  188.  
  189. /*
  190.  * undo all editing, restore the entry before we started editing
  191.  */
  192.  
  193. undo_new_entry()
  194. {
  195.     if (edit.editing) {
  196.         destroy_text_popup();
  197.         destroy_recycle_popup();
  198.         destroy_advance_popup();
  199.         destroy_entry(&edit.entry);
  200.         edit.editing = FALSE;
  201.         edit.changed = FALSE;
  202.         sensitize_edit_buttons();
  203.         draw_list(edit.menu);
  204.     }
  205. }
  206.  
  207.  
  208. /*
  209.  * user entered text into one of the buttons in the entry list
  210.  */
  211.  
  212. got_entry_text(lw, x, y, text)
  213.     struct listmenu        *lw;        /* which menu */
  214.     int            x, y;        /* which column/row */
  215.     char            *text;        /* text input by user */
  216. {
  217.     register struct entry    *ep;        /* affected entry */
  218.     register char        *p;        /* to remove trailing \n's */
  219.  
  220.     ep = &edit.entry;
  221.     switch(x) {
  222.       case SC_DATE:
  223.         if (*text) {
  224.             time_t temp = parse_datestring(text, 0);
  225.             if (temp > EON)
  226.                 ep->time = ep->time % 86400 + temp;
  227.         }
  228.         edit_list_button(TRUE, lw, SC_TIME, y);
  229.         print_button(lw->entry[y][SC_DATE],
  230.                     mkbuttonstring(lw, SC_DATE, y));
  231.         break;
  232.  
  233.       case SC_TIME:
  234.         if (*text == '-') {
  235.             ep->notime = TRUE;
  236.             ep->time -= ep->time % 86400;
  237.         } else if (*text) {
  238.             ep->notime = FALSE;
  239.             ep->time -= ep->time % 86400;
  240.             ep->time += parse_timestring(text);
  241.         }
  242.         edit_list_button(TRUE,lw, ep->notime ? SC_NOTE : SC_LENGTH, y);
  243.         print_button(lw->entry[y][SC_TIME],
  244.                     mkbuttonstring(lw, SC_TIME, y));
  245.         break;
  246.  
  247.       case SC_LENGTH: {
  248.         time_t length;
  249.         while (*text == ' ') text++;
  250.         length = *text==0 ? 0 :
  251.              *text=='-' ? parse_timestring(text+1) - ep->time%86400
  252.                     : parse_timestring(text);
  253.         if (length < 0)
  254.             length = 0;
  255.         if (length > 86400)
  256.             length = 86400;
  257.         ep->length = length;
  258.         edit_list_button(TRUE, lw, config.bigwarning && !ep->notime ?
  259.                     SC_ADVANCE : SC_NOTE, y);
  260.         print_button(lw->entry[y][SC_LENGTH],
  261.                     mkbuttonstring(lw, SC_LENGTH, y));
  262.         break; }
  263.  
  264.       case SC_ADVANCE:
  265.         parse_warnstring(text, &ep->early_warn, &ep->late_warn,
  266.                             &ep->noalarm);
  267.         edit_list_button(TRUE, lw, SC_NOTE, y);
  268.         print_button(lw->entry[y][SC_ADVANCE],
  269.                     mkbuttonstring(lw, SC_ADVANCE, y));
  270.         break;
  271.  
  272.       case SC_NOTE:
  273.         if (ep->note)
  274.             free(ep->note);
  275.         ep->note = 0;
  276.         while (*text && (*text == ' ' || *text == '\t'))
  277.             text++;
  278.         for (p=text+strlen(text)-1; p != text &&
  279.             (*p == '\n' || *p == '\t' || *p == ' '); *p-- = 0);
  280.         for (p=text; *p; p++)
  281.             if (*p == '\n') *p = ' ';
  282.         if (*text)
  283.             ep->note = mystrdup(text);
  284.         edit_list_button(FALSE, lw, 0, 0);
  285.         print_button(lw->entry[y][SC_NOTE],
  286.                     mkbuttonstring(lw, SC_NOTE, y));
  287.         XmProcessTraversal(lw->done, XmTRAVERSE_CURRENT);
  288.     }
  289.     edit.changed = TRUE;
  290.     edit.entry.suspended = FALSE;
  291.     if (x == SC_NOTE) /* eoln */
  292.         confirm_new_entry();
  293.     sensitize_edit_buttons();
  294. }
  295.  
  296.  
  297. /*
  298.  * while a new entry is being edited, it is kept in the <edit> struct,
  299.  * which overrides the appropriate entry (if any) in the mainlist. If
  300.  * it is being edited, the Confirm button should be sensitive. If it is
  301.  * being edited and has been changed, the Undo button should be sensitive.
  302.  */
  303.  
  304. sensitize_edit_buttons()
  305. {
  306.     Arg            args;
  307.  
  308.     if (edit.menu) {
  309.         XtSetArg(args, XmNsensitive, edit.changed);
  310.         XtSetValues(edit.menu->confirm, &args, 1);
  311.         XtSetArg(args, XmNsensitive, edit.changed);
  312.         XtSetValues(edit.menu->undo,    &args, 1);
  313.         XtSetArg(args, XmNsensitive, edit.editing);
  314.         XtSetValues(edit.menu->dup,     &args, 1);
  315.         XtSetArg(args, XmNsensitive, edit.editing);
  316.         XtSetValues(edit.menu->del,     &args, 1);
  317.     }
  318. }
  319.